library(tidyverse) 
library(nls.multstart) 
library(broom)
freenome_colors <- c('#948DFF', '#1DE3FE', '#BBD532', '#FF9D42',  '#FC2E7B', 
                   '#FECDD1')

Import Data

panel_1 <- readxl::read_xlsx(here::here("data", "reproducibility-study", "raw", 
                             "betalot_reproducibility_dataframes.xlsx"), 
                  sheet = 1) %>% 
  janitor::clean_names()

panel_2 <- readxl::read_xlsx(here::here("data", "reproducibility-study", "raw", 
                             "betalot_reproducibility_dataframes.xlsx"), 
                  sheet = 2) %>% 
  janitor::clean_names()


standards_panel_1 <- panel_1 %>% 
  filter(sample_type == "standard") 

standards_panel_2 <- panel_2 %>% 
  filter(sample_type == "standard")

From the analysis here we see that plate 3 on panel 1 is the best plate in terms of bead counts and plate 2 on panel 1 is the best.

We will choose these 2 plates to work with for our simulation set up

standards_panel_1 <- panel_1 %>% 
  filter(sample_type == "standard") %>% 
  filter(plate_number == "Plate 3")
standards_panel_2 <- panel_2 %>% 
  filter(sample_type == "standard") %>% 
  filter(plate_number == "Plate 2")

combined_standards <- bind_rows(standards_panel_1, standards_panel_2)
rc_panel1 <- panel_1 %>% 
  filter(plate_number == "Plate 3") %>% 
  filter(sample_type == "sample") %>% 
  filter(xponent_id != "Assay Buffer")

rc_panel2 <- panel_2 %>% 
  filter(plate_number == "Plate 2") %>% 
  filter(sample_type == "sample") %>% 
  filter(xponent_id != "Assay Buffer")

combined_rc <- bind_rows(rc_panel1, rc_panel2)
  1. 5PL curve fit
logistic_5pl <- function(d, a, median_mfi, c, b, g) {
  return(d + (a-d)/(a + (median_mfi/c)^b)^g)
}
  1. Pick one set of standards to work with to test the 5PL fit
  1. Fit Model
afp_tmp <- nls.multstart::nls_multstart(standard_expected_concentration ~ 
                                          logistic_5pl(d, a, median_mfi = median_mfi, 
                                                       c, b, g), 
                                        data = afp_std, 
                                        iter = 10000, 
                                        modelweights = 1/standard_expected_concentration^2,
                                        start_lower = c(a = -1, b = -1, c = 100, d = -1, 
                                                        g = -1), 
                                        start_upper = c(a = 1, b = 1, c = 200, d = 1, 
                                                        g = 1), 
                                        supp_errors = "Y", 
                                        control = nls.control(maxiter = 10000, 
                                                              minFactor=1e-7, 
                                                              tol=1e-5, 
                                                              printEval=F, 
                                                              warnOnly=F))

afp_tmp
Nonlinear regression model
  model: standard_expected_concentration ~ logistic_5pl(d, a, median_mfi = median_mfi,     c, b, g)
   data: data
         d          a          c          b          g 
-32.970879  -0.001301 125.968679  -1.101397   0.880800 
 weighted residual sum-of-squares: 1.418

Number of iterations to convergence: 41 
Achieved convergence tolerance: 1.49e-08
  1. Check agreement between xponent and nls
## xponent vs R fit 
broom::augment(afp_tmp, newdata = afp_std) %>% 
  ggplot(.,aes(log(calc_conc), log(.fitted))) + 
  geom_point() + 
  theme_classic() + 
  labs(title = "xponent vs R fit", 
       x = "xponent", y = "R fit")

## Absolute difference in fitted R vs fitted xponent 
broom::augment(afp_tmp, newdata = afp_std) %>% 
  mutate(diff = abs(calc_conc - .fitted)) %>% 
  ggplot(aes(diff)) + 
  geom_histogram() + 
  theme_classic() + 
  labs(title = paste0("Absolute Difference in xponent fit vs R fit (", 
                      afp_std$conc_units[1], ")"))
  

broom::augment(afp_tmp, newdata = afp_std) %>% 
  mutate(diff = abs(calc_conc - .fitted)) %>% 
  filter(diff > 1000)

## RECOVERY  
broom::augment(afp_tmp, newdata = afp_std) %>% 
  mutate(recov_nls = 100*(.fitted)/standard_expected_concentration) %>% 
  ggplot(.,aes(pct_recovery, recov_nls)) + 
  geom_point() + 
  theme_classic() + 
  labs(y = "custom R fit", x = "xponent fit", title = "% Recovery") + 
  scale_x_continuous(breaks = seq(88, 120, by = 2)) + 
  scale_y_continuous(breaks = seq(88, 120, by = 2))

broom::augment(afp_tmp, newdata = afp_std) %>% 
  mutate(recov_nls = 100*(.fitted)/standard_expected_concentration) %>% 
  mutate(recov_diff = abs(recov_nls - pct_recovery)) %>% 
  ggplot(.,aes(recov_diff)) + 
  geom_histogram() + 
  theme_classic() + 
  labs(title = paste0("Absolute Difference in xponent fit vs R fit (% Recovery)"))


broom::augment(afp_tmp, newdata = afp_std) %>% 
  mutate(recov_nls = 100*(.fitted)/standard_expected_concentration) %>% 
  mutate(recov_diff = abs(recov_nls - pct_recovery)) %>% 
  filter(recov_diff > 2)

Standard Curve Replicates

Now that we see a reasonably good agreement between the two curves, we can proceed with our simulation study

Simulation set up
1. We have a tibble/data frame
2. Randomly select n well columns for each assay
3. Fit the curve on that data
4. Check if it has converged 4. Calculate expected recovery for each standard
5. Calculate the concentration of the run controls using this fit

Things I need to

  1. Function that fits the model
fit_5pl <- function(df = NULL){
  nls.multstart::nls_multstart(standard_expected_concentration ~ 
                                          logistic_5pl(d, a, median_mfi = median_mfi, 
                                                       c, b, g), 
                                        data = df, 
                                        iter = 100000, 
                                        modelweights = 1/standard_expected_concentration^2,
                                        start_lower = c(a = -1, b = -1, c = 100, d = -1, 
                                                        g = -1), 
                                        start_upper = c(a = 1, b = 1, c = 200, d = 1, 
                                                        g = 1), 
                                        supp_errors = "Y", 
                                        control = nls.control(maxiter = 100000, 
                                                              minFactor=1e-7, 
                                                              tol=1e-5, 
                                                              printEval=F, 
                                                              warnOnly=F))
}

Reference standard concentrations

We also need a column that indicates the concentration using all 24 replicates of the plate (currently, luminex only calculates the conc for 8 replicates)

Test Chunk/Playground

temp_df <- combn(24, 2) %>%
    as.matrix() %>%
    data.frame() %>%
    select(sample(1:ncol(.), 1)) %>%
    rename(well_column = 1) %>%
    inner_join(., new_combined) %>% 
    filter(assay == "AFP") %>% 
    group_by(xponent_id) %>% 
    mutate(cv = 100*sd(median_mfi)/mean(median_mfi)) %>% 
    ungroup()
  
  tmp_columns <- temp_df %>% 
    select(well_column) %>% 
    distinct(well_column)
  
  tmp_model <- fit_5pl(df = temp_df)
  conv_log <- broom::glance(tmp_model) %>%
              select(isConv) %>%
              pull()
  
  #### Here we add RCs to the sampled_df 
  rc <- rc_calculated %>% 
    filter(assay == "AFP") %>%
    inner_join(tmp_columns)
  
  temp_df <- bind_rows(temp_df, rc)

  ## this will have backcalculated std concentrations and RCs 
  augmented_df <- broom::augment(tmp_model, newdata = temp_df) %>% 
    mutate(recov_sim = 100*(.fitted)/standard_expected_concentration, 
           num_reps_used = rep(2, nrow(.)), 
           conv = rep(as.character(conv_log), nrow(.)))
  augmented_df %>% 
    filter(sample_type == "sample") %>% 
    ggplot(.,aes(calc_conc, nls_conc)) + 
    geom_point()
  
  augmented_df %>% 
    filter(sample_type == "standard") %>% 
    ggplot(.,aes(recov_sim, pct_recovery)) + 
    geom_point()   
  
  1. Function to create what we need
iterate_model <- function(replicates = NULL,
                          protein = "NULL") {
  
  sampled_df <- combn(24, replicates) %>%
    as.matrix() %>%
    data.frame() %>%
    select(sample(1:ncol(.), 1)) %>%
    rename(well_column = 1) %>%
    inner_join(., new_combined) %>% 
    filter(assay == as.character(protein)) %>% 
    group_by(xponent_id) %>% 
    mutate(cv = 100*sd(median_mfi)/mean(median_mfi)) %>% 
    ungroup()
  
  well_columns <- sampled_df %>% 
    select(well_column) %>% 
    distinct(well_column)
  
  sampled_model <- fit_5pl(df = sampled_df)
  conv_log <- broom::glance(sampled_model) %>%
              select(isConv) %>%
              pull()
  
  #### Here we add RCs to the sampled_df 
  rc <- rc_calculated %>% 
    filter(assay == as.character(protein)) %>%
    inner_join(well_columns)
  
  sampled_df <- bind_rows(sampled_df, rc)

  ## this will have backcalculated std concentrations and RCs 
  augmented_df <- broom::augment(sampled_model, newdata = sampled_df) %>% 
    mutate(recov_sim = 100*(.fitted)/standard_expected_concentration, 
           num_reps_used = rep(replicates, nrow(.)), 
           conv = rep(as.character(conv_log), nrow(.)))
  
  return(augmented_df)
  
  
}

Now we need a way of iterating over all proteins

list_of_proteins <- combined_standards %>% select(assay) %>% 
  distinct() %>% 
  pull()
reps_2 <- imap_dfr(1:20, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model(replicates = 2, 
                                                   protein = .x)), 
                .id = "sim_number")

reps_3 <- imap_dfr(1:20, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model(replicates = 3, 
                                                   protein = .x)), 
                .id = "sim_number")

reps_4 <- imap_dfr(1:20, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model(replicates = 4, 
                                                   protein = .x)), 
                .id = "sim_number")

reps_5 <- imap_dfr(1:20, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model(replicates = 5, 
                                                   protein = .x)), 
                .id = "sim_number")

Bind these dataframes

sim_combined <- bind_rows(reps_2, reps_3, reps_4, reps_5)

sim_combined <- sim_combined %>% 
  mutate(nls_recov = 100*nls_conc/standard_expected_concentration)

reps_3 %>% 
  filter(assay == "AFP") %>% 
  filter(xponent_id == "Standard1")

Distribution of CVs

sim_combined %>% 
  mutate(num_reps_used = as.character(num_reps_used)) %>% 
  ggplot(.,aes(cv, fill = num_reps_used)) + 
  geom_histogram(alpha = 0.5) + 
  theme_classic() + 
  labs(title = "Distribution of CVs") + 
  scale_color_manual(values = freenome_colors[1:4])
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Warning: Removed 33600 rows containing non-finite values (stat_bin).

Recovery Absolute

sim_recov_plot <- function(std_point = "NULL") {
  sim_combined %>% 
  filter(xponent_id == std_point) %>% 
  mutate(num_reps_used = as.character(num_reps_used)) %>% 
  ggplot(.,aes(num_reps_used, recov_sim, group = num_reps_used)) + 
  geom_point() + 
  geom_boxplot(outlier.shape = NA) + 
  facet_wrap(vars(assay)) + 
  theme_classic() + 
  labs(title = paste0("Percent Recovery For ", std_point), 
       subtitle = "Recoveries from simulations")
}
map(list_of_standards, ~ sim_recov_plot(std_point = .x))
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Distribution of the differences in Recovery

map(list_of_standards, ~ sim_recov_diff_plot(std_point = .x))
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Run Controls

map(list_of_proteins, ~ rc_plot_avg(protein = .x))
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning: Removed 3 rows containing missing values (geom_point).

[[11]]
Warning: Removed 41 rows containing missing values (geom_point).
Warning: Removed 1 rows containing missing values (geom_point).

[[12]]

[[13]]

[[14]]

[[15]]
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning: Removed 8 rows containing missing values (geom_point).

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

Delete a standard

Replicates 4

Replicates 3

  1. For each protein, fit a model using all 24 standards and fix it
  2. Then for each protein, sample a set of RCs and predict their concentrations based on the model.

Fix standard, change number of replicates in the RCs

models %>%
  purrr::pluck("AFP")
Nonlinear regression model
  model: standard_expected_concentration ~ logistic_5pl(d, a, median_mfi = median_mfi,     c, b, g)
   data: data
         d          a          c          b          g 
-32.970554  -0.001301 125.968188  -1.101407   0.880794 
 weighted residual sum-of-squares: 1.418

Number of iterations to convergence: 50 
Achieved convergence tolerance: 1.49e-08
iterate_model_rc <- function(replicates = NULL,
                          protein = "NULL") {
  
  sampled_df <- combn(24, replicates) %>%
    as.matrix() %>%
    data.frame() %>%
    select(sample(1:ncol(.), 1)) %>%
    rename(well_column = 1) %>%
    inner_join(., new_combined) %>% 
    filter(assay == as.character(protein)) %>% 
    group_by(xponent_id) %>% 
    mutate(cv = 100*sd(median_mfi)/mean(median_mfi)) %>% 
    ungroup()
  
  well_columns <- sampled_df %>% 
    select(well_column) %>% 
    distinct(well_column)
  
   #fit_mod <- fit_5pl(df = standard_df)   
   #standard_df <- broom::augment(fit_mod, standard_df) %>% 
    #rename(nls_conc = .fitted)  
  
   
   rc <- rc_calculated %>% 
    filter(assay == as.character(protein)) %>%
    inner_join(well_columns)
  
  #sampled_df <- bind_rows(sampled_df, rc)

  ## this will have backcalculated Cs 
  fit_mod <- models %>% pluck(protein) 
  augmented_df <- broom::augment(fit_mod, newdata = rc) %>% 
    mutate(num_reps_used = rep(replicates, nrow(.)))
  
  return(augmented_df)
}
rc_reps_2 <- imap_dfr(1:100, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model_rc(replicates = 2, 
                                                   protein = .x)), 
                .id = "sim_number")

rc_reps_3 <- imap_dfr(1:100, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model_rc(replicates = 3, 
                                                   protein = .x)), 
                .id = "sim_number")

rc_reps_4 <- imap_dfr(1:100, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model_rc(replicates = 4, 
                                                   protein = .x)), 
                .id = "sim_number")

rc_reps_5 <- imap_dfr(1:100, ~map_dfr(list_of_proteins, ~ 
                                     iterate_model_rc(replicates = 5, 
                                                   protein = .x)), 
                .id = "sim_number")
rc_sim_combined <- bind_rows(rc_reps_2, rc_reps_3, rc_reps_4, rc_reps_5)  
rc_sim_combined
map(list_of_proteins, ~ rc_plot_avg(protein = .x))
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'xponent_id', 'sim_number', 'assay'. You can override using the `.groups` argument.
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

[[11]]
Warning: Removed 181 rows containing missing values (geom_point).
Warning: Removed 1 rows containing missing values (geom_point).

[[12]]

[[13]]

[[14]]

[[15]]

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

rc_cv_plot <- function(protein = "NULL") {
  rc_sim_combined %>% 
  group_by(assay, num_reps_used, xponent_id) %>% 
  summarise(avg = mean(log(.fitted + 1), na.rm = TRUE), 
            std_dev = sd(log(.fitted + 1), na.rm = TRUE), 
            cv = 100*(std_dev)/avg) %>% 
  mutate(xponent_id = fct_reorder(xponent_id, cv)) %>% 
  ungroup() %>% 
  filter(assay == protein) %>% 
  mutate(num_reps_used = as.character(num_reps_used)) %>% 
  ggplot(.,aes(xponent_id, cv)) + 
  geom_point(aes(color = num_reps_used)) + 
    labs(title = paste0(protein)) + 
    theme_classic() 
}
map(list_of_proteins, ~ rc_cv_plot(protein = .x)) 
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
Warning in log(.fitted + 1) : NaNs produced
`summarise()` has grouped output by 'assay', 'num_reps_used'. You can override using the `.groups` argument.
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

[[11]]

[[12]]

[[13]]

[[14]]

[[15]]

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

LS0tCnRpdGxlOiAiU3RhbmRhcmQgQ3VydmUgU2ltdWxhdGlvbnMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpIApsaWJyYXJ5KG5scy5tdWx0c3RhcnQpIApsaWJyYXJ5KGJyb29tKQpmcmVlbm9tZV9jb2xvcnMgPC0gYygnIzk0OERGRicsICcjMURFM0ZFJywgJyNCQkQ1MzInLCAnI0ZGOUQ0MicsICAnI0ZDMkU3QicsIAogICAgICAgICAgICAgICAgICAgJyNGRUNERDEnKQpgYGAKCgojIyMgSW1wb3J0IERhdGEgIAoKYGBge3J9CnBhbmVsXzEgPC0gcmVhZHhsOjpyZWFkX3hsc3goaGVyZTo6aGVyZSgiZGF0YSIsICJyZXByb2R1Y2liaWxpdHktc3R1ZHkiLCAicmF3IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJldGFsb3RfcmVwcm9kdWNpYmlsaXR5X2RhdGFmcmFtZXMueGxzeCIpLCAKICAgICAgICAgICAgICAgICAgc2hlZXQgPSAxKSAlPiUgCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQoKcGFuZWxfMiA8LSByZWFkeGw6OnJlYWRfeGxzeChoZXJlOjpoZXJlKCJkYXRhIiwgInJlcHJvZHVjaWJpbGl0eS1zdHVkeSIsICJyYXciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmV0YWxvdF9yZXByb2R1Y2liaWxpdHlfZGF0YWZyYW1lcy54bHN4IiksIAogICAgICAgICAgICAgICAgICBzaGVldCA9IDIpICU+JSAKICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpCgoKc3RhbmRhcmRzX3BhbmVsXzEgPC0gcGFuZWxfMSAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzdGFuZGFyZCIpIAoKc3RhbmRhcmRzX3BhbmVsXzIgPC0gcGFuZWxfMiAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzdGFuZGFyZCIpCmBgYAoKCkZyb20gdGhlIGFuYWx5c2lzIFtoZXJlXShodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9wcmVzZW50YXRpb24vZC8xRXFmMWRUVGRJX3g0SVdnSFE1T2t1TmxRVm8tcVJpbmtQVm5XYV9YTndUSS9lZGl0I3NsaWRlPWlkLmdmZDI5MGE5NDhjXzBfOSkgd2Ugc2VlIHRoYXQgcGxhdGUgMyBvbiBwYW5lbCAxIGlzIHRoZSBiZXN0IHBsYXRlIGluIHRlcm1zIG9mIGJlYWQgY291bnRzIGFuZCBwbGF0ZSAyIG9uIHBhbmVsIDEgaXMgdGhlIGJlc3QuIAoKV2Ugd2lsbCBjaG9vc2UgdGhlc2UgMiBwbGF0ZXMgdG8gd29yayB3aXRoIGZvciBvdXIgc2ltdWxhdGlvbiBzZXQgdXAgIAoKYGBge3J9CnN0YW5kYXJkc19wYW5lbF8xIDwtIHBhbmVsXzEgJT4lIAogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic3RhbmRhcmQiKSAlPiUgCiAgZmlsdGVyKHBsYXRlX251bWJlciA9PSAiUGxhdGUgMyIpCnN0YW5kYXJkc19wYW5lbF8yIDwtIHBhbmVsXzIgJT4lIAogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic3RhbmRhcmQiKSAlPiUgCiAgZmlsdGVyKHBsYXRlX251bWJlciA9PSAiUGxhdGUgMiIpCgpjb21iaW5lZF9zdGFuZGFyZHMgPC0gYmluZF9yb3dzKHN0YW5kYXJkc19wYW5lbF8xLCBzdGFuZGFyZHNfcGFuZWxfMikKYGBgCgoKYGBge3J9CnJjX3BhbmVsMSA8LSBwYW5lbF8xICU+JSAKICBmaWx0ZXIocGxhdGVfbnVtYmVyID09ICJQbGF0ZSAzIikgJT4lIAogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic2FtcGxlIikgJT4lIAogIGZpbHRlcih4cG9uZW50X2lkICE9ICJBc3NheSBCdWZmZXIiKQoKcmNfcGFuZWwyIDwtIHBhbmVsXzIgJT4lIAogIGZpbHRlcihwbGF0ZV9udW1iZXIgPT0gIlBsYXRlIDIiKSAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzYW1wbGUiKSAlPiUgCiAgZmlsdGVyKHhwb25lbnRfaWQgIT0gIkFzc2F5IEJ1ZmZlciIpCgpjb21iaW5lZF9yYyA8LSBiaW5kX3Jvd3MocmNfcGFuZWwxLCByY19wYW5lbDIpCmBgYAoKCgoKCjEuIDVQTCBjdXJ2ZSBmaXQgIAoKCmBgYHtyfQpsb2dpc3RpY181cGwgPC0gZnVuY3Rpb24oZCwgYSwgbWVkaWFuX21maSwgYywgYiwgZykgewogIHJldHVybihkICsgKGEtZCkvKGEgKyAobWVkaWFuX21maS9jKV5iKV5nKQp9CmBgYAoKMi4gUGljayBvbmUgc2V0IG9mIHN0YW5kYXJkcyB0byB3b3JrIHdpdGggIHRvIHRlc3QgdGhlIDVQTCBmaXQgIAoKYGBge3J9CmFmcF9zdGQgPC0gc3RhbmRhcmRzX3BhbmVsXzEgJT4lIAogIGZpbHRlcihhc3NheSA9PSAiQUZQIikgJT4lIAogIGZpbHRlcih3ZWxsX2NvbHVtbiA9PSAxIHwgd2VsbF9jb2x1bW4gPT0gMiB8IHdlbGxfY29sdW1uID09IDMgfCB3ZWxsX2NvbHVtbiA9PSA0IAogICAgICAgICB8IHdlbGxfY29sdW1uID09IDUgfCB3ZWxsX2NvbHVtbiA9PSA2IHwgd2VsbF9jb2x1bW4gPT0gNyB8IHdlbGxfY29sdW1uID09IDgpCmBgYAoKCjMuIEZpdCBNb2RlbCAKCmBgYHtyfQphZnBfdG1wIDwtIG5scy5tdWx0c3RhcnQ6Om5sc19tdWx0c3RhcnQoc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbiB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpc3RpY181cGwoZCwgYSwgbWVkaWFuX21maSA9IG1lZGlhbl9tZmksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYywgYiwgZyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGFmcF9zdGQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDEwMDAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsd2VpZ2h0cyA9IDEvc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbl4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRfbG93ZXIgPSBjKGEgPSAtMSwgYiA9IC0xLCBjID0gMTAwLCBkID0gLTEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSAtMSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRfdXBwZXIgPSBjKGEgPSAxLCBiID0gMSwgYyA9IDIwMCwgZCA9IDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSAxKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXBwX2Vycm9ycyA9ICJZIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbmxzLmNvbnRyb2wobWF4aXRlciA9IDEwMDAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5GYWN0b3I9MWUtNywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9sPTFlLTUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50RXZhbD1GLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJuT25seT1GKSkKCmFmcF90bXAKCgoKYGBgCgo0LiBDaGVjayBhZ3JlZW1lbnQgYmV0d2VlbiB4cG9uZW50IGFuZCBubHMgIAoKYGBge3J9CiMjIHhwb25lbnQgdnMgUiBmaXQgCmJyb29tOjphdWdtZW50KGFmcF90bXAsIG5ld2RhdGEgPSBhZnBfc3RkKSAlPiUgCiAgZ2dwbG90KC4sYWVzKGxvZyhjYWxjX2NvbmMpLCBsb2coLmZpdHRlZCkpKSArIAogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIGxhYnModGl0bGUgPSAieHBvbmVudCB2cyBSIGZpdCIsIAogICAgICAgeCA9ICJ4cG9uZW50IiwgeSA9ICJSIGZpdCIpCgojIyBBYnNvbHV0ZSBkaWZmZXJlbmNlIGluIGZpdHRlZCBSIHZzIGZpdHRlZCB4cG9uZW50IApicm9vbTo6YXVnbWVudChhZnBfdG1wLCBuZXdkYXRhID0gYWZwX3N0ZCkgJT4lIAogIG11dGF0ZShkaWZmID0gYWJzKGNhbGNfY29uYyAtIC5maXR0ZWQpKSAlPiUgCiAgZ2dwbG90KGFlcyhkaWZmKSkgKyAKICBnZW9tX2hpc3RvZ3JhbSgpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiQWJzb2x1dGUgRGlmZmVyZW5jZSBpbiB4cG9uZW50IGZpdCB2cyBSIGZpdCAoIiwgCiAgICAgICAgICAgICAgICAgICAgICBhZnBfc3RkJGNvbmNfdW5pdHNbMV0sICIpIikpCiAgCgpicm9vbTo6YXVnbWVudChhZnBfdG1wLCBuZXdkYXRhID0gYWZwX3N0ZCkgJT4lIAogIG11dGF0ZShkaWZmID0gYWJzKGNhbGNfY29uYyAtIC5maXR0ZWQpKSAlPiUgCiAgZmlsdGVyKGRpZmYgPiAxMDAwKQoKIyMgUkVDT1ZFUlkgIApicm9vbTo6YXVnbWVudChhZnBfdG1wLCBuZXdkYXRhID0gYWZwX3N0ZCkgJT4lIAogIG11dGF0ZShyZWNvdl9ubHMgPSAxMDAqKC5maXR0ZWQpL3N0YW5kYXJkX2V4cGVjdGVkX2NvbmNlbnRyYXRpb24pICU+JSAKICBnZ3Bsb3QoLixhZXMocGN0X3JlY292ZXJ5LCByZWNvdl9ubHMpKSArIAogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIGxhYnMoeSA9ICJjdXN0b20gUiBmaXQiLCB4ID0gInhwb25lbnQgZml0IiwgdGl0bGUgPSAiJSBSZWNvdmVyeSIpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSg4OCwgMTIwLCBieSA9IDIpKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoODgsIDEyMCwgYnkgPSAyKSkKCmJyb29tOjphdWdtZW50KGFmcF90bXAsIG5ld2RhdGEgPSBhZnBfc3RkKSAlPiUgCiAgbXV0YXRlKHJlY292X25scyA9IDEwMCooLmZpdHRlZCkvc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbikgJT4lIAogIG11dGF0ZShyZWNvdl9kaWZmID0gYWJzKHJlY292X25scyAtIHBjdF9yZWNvdmVyeSkpICU+JSAKICBnZ3Bsb3QoLixhZXMocmVjb3ZfZGlmZikpICsgCiAgZ2VvbV9oaXN0b2dyYW0oKSArIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZTAoIkFic29sdXRlIERpZmZlcmVuY2UgaW4geHBvbmVudCBmaXQgdnMgUiBmaXQgKCUgUmVjb3ZlcnkpIikpCgoKYnJvb206OmF1Z21lbnQoYWZwX3RtcCwgbmV3ZGF0YSA9IGFmcF9zdGQpICU+JSAKICBtdXRhdGUocmVjb3ZfbmxzID0gMTAwKiguZml0dGVkKS9zdGFuZGFyZF9leHBlY3RlZF9jb25jZW50cmF0aW9uKSAlPiUgCiAgbXV0YXRlKHJlY292X2RpZmYgPSBhYnMocmVjb3ZfbmxzIC0gcGN0X3JlY292ZXJ5KSkgJT4lIAogIGZpbHRlcihyZWNvdl9kaWZmID4gMikKYGBgCgoKCgojIyMgU3RhbmRhcmQgQ3VydmUgUmVwbGljYXRlcyAgIAoKTm93IHRoYXQgd2Ugc2VlIGEgcmVhc29uYWJseSBnb29kIGFncmVlbWVudCBiZXR3ZWVuIHRoZSB0d28gY3VydmVzLCB3ZSBjYW4gcHJvY2VlZCB3aXRoIG91ciBzaW11bGF0aW9uIHN0dWR5ICAgCgoKU2ltdWxhdGlvbiBzZXQgdXAgIAoxLiBXZSBoYXZlIGEgdGliYmxlL2RhdGEgZnJhbWUgICAKMi4gUmFuZG9tbHkgc2VsZWN0IG4gd2VsbCBjb2x1bW5zIGZvciBlYWNoIGFzc2F5ICAgCjMuIEZpdCB0aGUgY3VydmUgb24gdGhhdCBkYXRhICAgCjQuIENoZWNrIGlmIGl0IGhhcyBjb252ZXJnZWQgCjQuIENhbGN1bGF0ZSBleHBlY3RlZCByZWNvdmVyeSBmb3IgZWFjaCBzdGFuZGFyZCAgIAo1LiBDYWxjdWxhdGUgdGhlIGNvbmNlbnRyYXRpb24gb2YgdGhlIHJ1biBjb250cm9scyB1c2luZyB0aGlzIGZpdCAgCgoKCgoKCgpUaGluZ3MgSSBuZWVkIHRvIAoKMS4gRnVuY3Rpb24gdGhhdCBmaXRzIHRoZSBtb2RlbCAgCgpgYGB7cn0KZml0XzVwbCA8LSBmdW5jdGlvbihkZiA9IE5VTEwpewogIG5scy5tdWx0c3RhcnQ6Om5sc19tdWx0c3RhcnQoc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbiB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpc3RpY181cGwoZCwgYSwgbWVkaWFuX21maSA9IG1lZGlhbl9tZmksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYywgYiwgZyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSAxMDAwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWx3ZWlnaHRzID0gMS9zdGFuZGFyZF9leHBlY3RlZF9jb25jZW50cmF0aW9uXjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydF9sb3dlciA9IGMoYSA9IC0xLCBiID0gLTEsIGMgPSAxMDAsIGQgPSAtMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IC0xKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydF91cHBlciA9IGMoYSA9IDEsIGIgPSAxLCBjID0gMjAwLCBkID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IDEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cHBfZXJyb3JzID0gIlkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBubHMuY29udHJvbChtYXhpdGVyID0gMTAwMDAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5GYWN0b3I9MWUtNywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9sPTFlLTUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50RXZhbD1GLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJuT25seT1GKSkKfQpgYGAKCgojIyMgUmVmZXJlbmNlIHN0YW5kYXJkIGNvbmNlbnRyYXRpb25zICAKCldlIGFsc28gbmVlZCBhIGNvbHVtbiB0aGF0IGluZGljYXRlcyB0aGUgY29uY2VudHJhdGlvbiB1c2luZyBhbGwgMjQgcmVwbGljYXRlcyBvZiB0aGUgcGxhdGUgKGN1cnJlbnRseSwgbHVtaW5leCBvbmx5IGNhbGN1bGF0ZXMgdGhlIGNvbmMgZm9yIDggcmVwbGljYXRlcykgCgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIFN0YW5kYXJkIEN1cnZlcyAjIyMjIyMjIyMjIyMjIyMjCmNhbGNfbmxzX2NvbmMgPC0gZnVuY3Rpb24ocHJvdGVpbiA9ICJOVUxMIikgewogIGRmX21vZCA8LSBjb21iaW5lZF9zdGFuZGFyZHMgJT4lIAogICAgZmlsdGVyKGFzc2F5ID09IHByb3RlaW4pCiAgCiAgZml0X21vZCA8LSBmaXRfNXBsKGRmID0gZGZfbW9kKSAKICBkZl9tb2QgPC0gYnJvb206OmF1Z21lbnQoZml0X21vZCwgZGZfbW9kKSAlPiUgCiAgICByZW5hbWUobmxzX2NvbmMgPSAuZml0dGVkKQogIHJldHVybihkZl9tb2QpCn0gCgpsaXN0X29mX3Byb3RlaW5zIDwtIGNvbWJpbmVkX3N0YW5kYXJkcyAlPiUgc2VsZWN0KGFzc2F5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgcHVsbCgpCgpuZXdfY29tYmluZWQgPC0gbWFwX2RmcihsaXN0X29mX3Byb3RlaW5zLCB+IGNhbGNfbmxzX2NvbmMocHJvdGVpbiA9IC54KSkKCm5ld19jb21iaW5lZCA8LSBuZXdfY29tYmluZWQgJT4lIAogIG11dGF0ZShubHNfcmVjb3YgPSAxMDAqbmxzX2NvbmMvc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbikKCgoKIyMjIyMjIyMjIyMjIFJ1biBDb250cm9scyAjIyMjIyMjIyMjIyMjIyMjIwpjYWxjX3JjX2NvbmMgPC0gZnVuY3Rpb24ocHJvdGVpbiA9ICJOVUxMIikgewogIAogIGRmX21vZCA8LSBjb21iaW5lZF9zdGFuZGFyZHMgJT4lIAogICAgZmlsdGVyKGFzc2F5ID09IHByb3RlaW4pCiAgCiAgcmMgPC0gY29tYmluZWRfcmMgJT4lIAogICAgZmlsdGVyKGFzc2F5ID09IHByb3RlaW4pIAogIAogIGZpdF9tb2QgPC0gZml0XzVwbChkZiA9IGRmX21vZCkgCiAgCiAgcmMgPC0gYnJvb206OmF1Z21lbnQoZml0X21vZCwgbmV3ZGF0YSA9IHJjKSAlPiUgCiAgICByZW5hbWUobmxzX2NvbmMgPSAuZml0dGVkKQogIHJldHVybihyYykKfSAKCnJjX2NhbGN1bGF0ZWQgPC0gbWFwX2RmcihsaXN0X29mX3Byb3RlaW5zLCB+IGNhbGNfcmNfY29uYyhwcm90ZWluID0gLngpKQoKcmNfY2FsY3VsYXRlZCAlPiUgCiAgICBnZ3Bsb3QoLixhZXMoY2FsY19jb25jLCBubHNfY29uYykpICsgCiAgIGdlb21fcG9pbnQoKSArIAogICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKSArIAogICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkKCnJjX2NhbGN1bGF0ZWQgJT4lIAogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic2FtcGxlIikgJT4lIAogIGdyb3VwX2J5KHhwb25lbnRfaWQsIGFzc2F5KSAlPiUgCiAgc3VtbWFyaXNlKG5sc19jb25jID0gbWVhbihubHNfY29uYykpCmBgYAoKCgoKKipUZXN0IENodW5rL1BsYXlncm91bmQqKiAgIAoKYGBge3J9CnRlbXBfZGYgPC0gY29tYm4oMjQsIDIpICU+JQogICAgYXMubWF0cml4KCkgJT4lCiAgICBkYXRhLmZyYW1lKCkgJT4lCiAgICBzZWxlY3Qoc2FtcGxlKDE6bmNvbCguKSwgMSkpICU+JQogICAgcmVuYW1lKHdlbGxfY29sdW1uID0gMSkgJT4lCiAgICBpbm5lcl9qb2luKC4sIG5ld19jb21iaW5lZCkgJT4lIAogICAgZmlsdGVyKGFzc2F5ID09ICJBRlAiKSAlPiUgCiAgICBncm91cF9ieSh4cG9uZW50X2lkKSAlPiUgCiAgICBtdXRhdGUoY3YgPSAxMDAqc2QobWVkaWFuX21maSkvbWVhbihtZWRpYW5fbWZpKSkgJT4lIAogICAgdW5ncm91cCgpCiAgCiAgdG1wX2NvbHVtbnMgPC0gdGVtcF9kZiAlPiUgCiAgICBzZWxlY3Qod2VsbF9jb2x1bW4pICU+JSAKICAgIGRpc3RpbmN0KHdlbGxfY29sdW1uKQogIAogIHRtcF9tb2RlbCA8LSBmaXRfNXBsKGRmID0gdGVtcF9kZikKICBjb252X2xvZyA8LSBicm9vbTo6Z2xhbmNlKHRtcF9tb2RlbCkgJT4lCiAgICAgICAgICAgICAgc2VsZWN0KGlzQ29udikgJT4lCiAgICAgICAgICAgICAgcHVsbCgpCiAgCiAgIyMjIyBIZXJlIHdlIGFkZCBSQ3MgdG8gdGhlIHNhbXBsZWRfZGYgCiAgcmMgPC0gcmNfY2FsY3VsYXRlZCAlPiUgCiAgICBmaWx0ZXIoYXNzYXkgPT0gIkFGUCIpICU+JQogICAgaW5uZXJfam9pbih0bXBfY29sdW1ucykKICAKICB0ZW1wX2RmIDwtIGJpbmRfcm93cyh0ZW1wX2RmLCByYykKCiAgIyMgdGhpcyB3aWxsIGhhdmUgYmFja2NhbGN1bGF0ZWQgc3RkIGNvbmNlbnRyYXRpb25zIGFuZCBSQ3MgCiAgYXVnbWVudGVkX2RmIDwtIGJyb29tOjphdWdtZW50KHRtcF9tb2RlbCwgbmV3ZGF0YSA9IHRlbXBfZGYpICU+JSAKICAgIG11dGF0ZShyZWNvdl9zaW0gPSAxMDAqKC5maXR0ZWQpL3N0YW5kYXJkX2V4cGVjdGVkX2NvbmNlbnRyYXRpb24sIAogICAgICAgICAgIG51bV9yZXBzX3VzZWQgPSByZXAoMiwgbnJvdyguKSksIAogICAgICAgICAgIGNvbnYgPSByZXAoYXMuY2hhcmFjdGVyKGNvbnZfbG9nKSwgbnJvdyguKSkpCiAgYXVnbWVudGVkX2RmICU+JSAKICAgIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic2FtcGxlIikgJT4lIAogICAgZ2dwbG90KC4sYWVzKGNhbGNfY29uYywgbmxzX2NvbmMpKSArIAogICAgZ2VvbV9wb2ludCgpCiAgCiAgYXVnbWVudGVkX2RmICU+JSAKICAgIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic3RhbmRhcmQiKSAlPiUgCiAgICBnZ3Bsb3QoLixhZXMocmVjb3Zfc2ltLCBwY3RfcmVjb3ZlcnkpKSArIAogICAgZ2VvbV9wb2ludCgpICAgCiAgCmBgYAoKCgoyLiBGdW5jdGlvbiB0byBjcmVhdGUgd2hhdCB3ZSBuZWVkICAKCmBgYHtyfQppdGVyYXRlX21vZGVsIDwtIGZ1bmN0aW9uKHJlcGxpY2F0ZXMgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlaW4gPSAiTlVMTCIpIHsKICAKICBzYW1wbGVkX2RmIDwtIGNvbWJuKDI0LCByZXBsaWNhdGVzKSAlPiUKICAgIGFzLm1hdHJpeCgpICU+JQogICAgZGF0YS5mcmFtZSgpICU+JQogICAgc2VsZWN0KHNhbXBsZSgxOm5jb2woLiksIDEpKSAlPiUKICAgIHJlbmFtZSh3ZWxsX2NvbHVtbiA9IDEpICU+JQogICAgaW5uZXJfam9pbiguLCBuZXdfY29tYmluZWQpICU+JSAKICAgIGZpbHRlcihhc3NheSA9PSBhcy5jaGFyYWN0ZXIocHJvdGVpbikpICU+JSAKICAgIGdyb3VwX2J5KHhwb25lbnRfaWQpICU+JSAKICAgIG11dGF0ZShjdiA9IDEwMCpzZChtZWRpYW5fbWZpKS9tZWFuKG1lZGlhbl9tZmkpKSAlPiUgCiAgICB1bmdyb3VwKCkKICAKICB3ZWxsX2NvbHVtbnMgPC0gc2FtcGxlZF9kZiAlPiUgCiAgICBzZWxlY3Qod2VsbF9jb2x1bW4pICU+JSAKICAgIGRpc3RpbmN0KHdlbGxfY29sdW1uKQogIAogIHNhbXBsZWRfbW9kZWwgPC0gZml0XzVwbChkZiA9IHNhbXBsZWRfZGYpCiAgY29udl9sb2cgPC0gYnJvb206OmdsYW5jZShzYW1wbGVkX21vZGVsKSAlPiUKICAgICAgICAgICAgICBzZWxlY3QoaXNDb252KSAlPiUKICAgICAgICAgICAgICBwdWxsKCkKICAKICAjIyMjIEhlcmUgd2UgYWRkIFJDcyB0byB0aGUgc2FtcGxlZF9kZiAKICByYyA8LSByY19jYWxjdWxhdGVkICU+JSAKICAgIGZpbHRlcihhc3NheSA9PSBhcy5jaGFyYWN0ZXIocHJvdGVpbikpICU+JQogICAgaW5uZXJfam9pbih3ZWxsX2NvbHVtbnMpCiAgCiAgc2FtcGxlZF9kZiA8LSBiaW5kX3Jvd3Moc2FtcGxlZF9kZiwgcmMpCgogICMjIHRoaXMgd2lsbCBoYXZlIGJhY2tjYWxjdWxhdGVkIHN0ZCBjb25jZW50cmF0aW9ucyBhbmQgUkNzIAogIGF1Z21lbnRlZF9kZiA8LSBicm9vbTo6YXVnbWVudChzYW1wbGVkX21vZGVsLCBuZXdkYXRhID0gc2FtcGxlZF9kZikgJT4lIAogICAgbXV0YXRlKHJlY292X3NpbSA9IDEwMCooLmZpdHRlZCkvc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbiwgCiAgICAgICAgICAgbnVtX3JlcHNfdXNlZCA9IHJlcChyZXBsaWNhdGVzLCBucm93KC4pKSwgCiAgICAgICAgICAgY29udiA9IHJlcChhcy5jaGFyYWN0ZXIoY29udl9sb2cpLCBucm93KC4pKSkKICAKICByZXR1cm4oYXVnbWVudGVkX2RmKQogIAogIAp9CmBgYAoKCgpOb3cgd2UgbmVlZCBhIHdheSBvZiBpdGVyYXRpbmcgb3ZlciBhbGwgcHJvdGVpbnMgCgpgYGB7cn0KbGlzdF9vZl9wcm90ZWlucyA8LSBjb21iaW5lZF9zdGFuZGFyZHMgJT4lIHNlbGVjdChhc3NheSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIHB1bGwoKQpgYGAKCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpyZXBzXzIgPC0gaW1hcF9kZnIoMToyMCwgfm1hcF9kZnIobGlzdF9vZl9wcm90ZWlucywgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGVfbW9kZWwocmVwbGljYXRlcyA9IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWluID0gLngpKSwgCiAgICAgICAgICAgICAgICAuaWQgPSAic2ltX251bWJlciIpCgpyZXBzXzMgPC0gaW1hcF9kZnIoMToyMCwgfm1hcF9kZnIobGlzdF9vZl9wcm90ZWlucywgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGVfbW9kZWwocmVwbGljYXRlcyA9IDMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWluID0gLngpKSwgCiAgICAgICAgICAgICAgICAuaWQgPSAic2ltX251bWJlciIpCgpyZXBzXzQgPC0gaW1hcF9kZnIoMToyMCwgfm1hcF9kZnIobGlzdF9vZl9wcm90ZWlucywgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGVfbW9kZWwocmVwbGljYXRlcyA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWluID0gLngpKSwgCiAgICAgICAgICAgICAgICAuaWQgPSAic2ltX251bWJlciIpCgpyZXBzXzUgPC0gaW1hcF9kZnIoMToyMCwgfm1hcF9kZnIobGlzdF9vZl9wcm90ZWlucywgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGVfbW9kZWwocmVwbGljYXRlcyA9IDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWluID0gLngpKSwgCiAgICAgICAgICAgICAgICAuaWQgPSAic2ltX251bWJlciIpCmBgYAoKCgpCaW5kIHRoZXNlIGRhdGFmcmFtZXMgICAKCmBgYHtyfQpzaW1fY29tYmluZWQgPC0gYmluZF9yb3dzKHJlcHNfMiwgcmVwc18zLCByZXBzXzQsIHJlcHNfNSkKCnNpbV9jb21iaW5lZCA8LSBzaW1fY29tYmluZWQgJT4lIAogIG11dGF0ZShubHNfcmVjb3YgPSAxMDAqbmxzX2NvbmMvc3RhbmRhcmRfZXhwZWN0ZWRfY29uY2VudHJhdGlvbikKCnJlcHNfMyAlPiUgCiAgZmlsdGVyKGFzc2F5ID09ICJBRlAiKSAlPiUgCiAgZmlsdGVyKHhwb25lbnRfaWQgPT0gIlN0YW5kYXJkMSIpCmBgYAoKCkRpc3RyaWJ1dGlvbiBvZiBDVnMgIAoKYGBge3J9CnNpbV9jb21iaW5lZCAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMoY3YsIGZpbGwgPSBudW1fcmVwc191c2VkKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShhbHBoYSA9IDAuNSkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBDVnMiKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBmcmVlbm9tZV9jb2xvcnNbMTo0XSkKYGBgCiMjIyMgUmVjb3ZlcnkgQWJzb2x1dGUgIAoKYGBge3J9CnNpbV9yZWNvdl9wbG90IDwtIGZ1bmN0aW9uKHN0ZF9wb2ludCA9ICJOVUxMIikgewogIHNpbV9jb21iaW5lZCAlPiUgCiAgZmlsdGVyKHhwb25lbnRfaWQgPT0gc3RkX3BvaW50KSAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMobnVtX3JlcHNfdXNlZCwgcmVjb3Zfc2ltLCBncm91cCA9IG51bV9yZXBzX3VzZWQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsgCiAgZmFjZXRfd3JhcCh2YXJzKGFzc2F5KSkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUwKCJQZXJjZW50IFJlY292ZXJ5IEZvciAiLCBzdGRfcG9pbnQpLCAKICAgICAgIHN1YnRpdGxlID0gIlJlY292ZXJpZXMgZnJvbSBzaW11bGF0aW9ucyIpCn0KYGBgCgoKYGBge3J9CnNpbV9jb21iaW5lZCAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzdGFuZGFyZCIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeHBvbmVudF9pZCwgbmxzX3JlY292KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArIAogIGZhY2V0X3dyYXAodmFycyhhc3NheSkpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKCgpzaW1fY29tYmluZWQgJT4lIAogIGZpbHRlcih4cG9uZW50X2lkID09ICJTdGFuZGFyZDIiKSAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMobnVtX3JlcHNfdXNlZCwgbmxzX3JlY292LCBncm91cCA9IG51bV9yZXBzX3VzZWQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGdlb21fcG9pbnQoYWVzKHkgPSBwY3RfcmVjb3ZlcnkpLCBjb2xvciA9ICJyZWQiLCBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArIAogIGZhY2V0X3dyYXAodmFycyhhc3NheSkpICAKCmxpc3Rfb2Zfc3RhbmRhcmRzIDwtIGMoIlN0YW5kYXJkMSIsICJTdGFuZGFyZDIiLCAiU3RhbmRhcmQzIiwgIlN0YW5kYXJkNCIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGFuZGFyZDUiLCAiU3RhbmRhcmQ2IikgCgptYXAobGlzdF9vZl9zdGFuZGFyZHMsIH4gc2ltX3JlY292X3Bsb3Qoc3RkX3BvaW50ID0gLngpKQpgYGAKCgojIyMjIERpc3RyaWJ1dGlvbiBvZiB0aGUgZGlmZmVyZW5jZXMgaW4gUmVjb3ZlcnkgICAgCgoKCmBgYHtyfQpzaW1fY29tYmluZWQgPC0gc2ltX2NvbWJpbmVkICU+JSAKICBtdXRhdGUocmVjb3ZfZGlmZiA9IGFicyhyZWNvdl9zaW0gLSBubHNfcmVjb3YpKQoKc2ltX3JlY292X2RpZmZfcGxvdCA8LSBmdW5jdGlvbihzdGRfcG9pbnQgPSAiTlVMTCIpIHsKICBzaW1fY29tYmluZWQgJT4lIAogIGZpbHRlcih4cG9uZW50X2lkID09IHN0ZF9wb2ludCkgJT4lIAogIGZpbHRlcihhc3NheSAhPSAiQ0ExNS0zIikgJT4lIAogICAgZmlsdGVyKGFzc2F5ICE9ICJNSUYiKSAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMobnVtX3JlcHNfdXNlZCwgcmVjb3ZfZGlmZiwgZ3JvdXAgPSBudW1fcmVwc191c2VkKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArIAogIGZhY2V0X3dyYXAodmFycyhhc3NheSkpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiUGVyY2VudCBSZWNvdmVyeSBEaWZmZXJlbmNlIEZvciAiLCBzdGRfcG9pbnQpLCAKICAgICAgIHN1YnRpdGxlID0gIiIpCn0KCnNpbV9jb21iaW5lZCAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMobnVtX3JlcHNfdXNlZCwgcmVjb3ZfZGlmZiwgZ3JvdXAgPSBudW1fcmVwc191c2VkKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAwLjI1KSArIAogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKSArIAogIHRoZW1lX2NsYXNzaWMoKQoKbWFwKGxpc3Rfb2Zfc3RhbmRhcmRzLCB+IHNpbV9yZWNvdl9kaWZmX3Bsb3Qoc3RkX3BvaW50ID0gLngpKQpgYGAKCgoKCiMjIyMgUnVuIENvbnRyb2xzICAgCgpgYGB7cn0Kc2ltX2NvbWJpbmVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBmaWx0ZXIobnVtX3JlcHNfdXNlZCA9PSAyKSAlPiUgCiAgI211dGF0ZShhYnNfZGlmZiA9IGFicyhjYWxjX2NvbmMgLSBubHNfY29uYykpICU+JSAKICBnZ3Bsb3QoLixhZXMoY2FsY19jb25jICsgMSwgbmxzX2NvbmMgKyAxKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKQoKc2ltX2NvbWJpbmVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBmaWx0ZXIobnVtX3JlcHNfdXNlZCA9PSAzKSAlPiUgCiAgI211dGF0ZShhYnNfZGlmZiA9IGFicyhjYWxjX2NvbmMgLSBubHNfY29uYykpICU+JSAKICBnZ3Bsb3QoLixhZXMoY2FsY19jb25jICsgMSwgbmxzX2NvbmMgKyAxKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKQoKc2ltX2NvbWJpbmVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBmaWx0ZXIobnVtX3JlcHNfdXNlZCA9PSA0KSAlPiUgCiAgI211dGF0ZShhYnNfZGlmZiA9IGFicyhjYWxjX2NvbmMgLSBubHNfY29uYykpICU+JSAKICBnZ3Bsb3QoLixhZXMoY2FsY19jb25jICsgMSwgbmxzX2NvbmMgKyAxKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKQoKc2ltX2NvbWJpbmVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBmaWx0ZXIobnVtX3JlcHNfdXNlZCA9PSA1KSAlPiUgCiAgI211dGF0ZShhYnNfZGlmZiA9IGFicyhjYWxjX2NvbmMgLSBubHNfY29uYykpICU+JSAKICBnZ3Bsb3QoLixhZXMoY2FsY19jb25jICsgMSwgbmxzX2NvbmMgKyAxKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICBmYWNldF93cmFwKHZhcnMoYXNzYXkpKQoKCgpyY19wbG90X29uZSA8LSBmdW5jdGlvbihwcm90ZWluID0gIk5VTEwiKSB7CiAgc2ltX2NvbWJpbmVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBmaWx0ZXIoYXNzYXkgPT0gcHJvdGVpbikgJT4lIAogIG11dGF0ZShudW1fcmVwc191c2VkID0gYXMuY2hhcmFjdGVyKG51bV9yZXBzX3VzZWQpKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHhwb25lbnRfaWQsIGxvZyguZml0dGVkICsxKSwgZ3JvdXAgPSBudW1fcmVwc191c2VkLCAKICAgICAgICAgICAgICAgY29sb3IgPSBudW1fcmVwc191c2VkKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArIAogIGdlb21fcG9pbnQoYWVzKHhwb25lbnRfaWQsIGxvZyhubHNfY29uYyArIDEpKSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjUpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiUnVuIENvbnRyb2xzIEZvciAiLCBwcm90ZWluKSwgCiAgICAgICBzdWJ0aXRsZSA9ICJEYXJrIEJsdWUgUG9pbnRzIGFyZSBmaXR0ZWQgdmFsdWVzIHVzaW5nIGFsbCAyNCBzdGFuZGFyZHMiKQp9CgojIyMjIHdlIG5lZWQgYSBkYXRhIHNldCB3aGVyZSB0aGUgUkNzIGFyZSBtZWFuIG9mIDI0IHJlcGxpY2F0ZXMgIApyY19hdmcgPC0gcmNfY2FsY3VsYXRlZCAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzYW1wbGUiKSAlPiUgCiAgZ3JvdXBfYnkoYXNzYXksIHhwb25lbnRfaWQpICU+JSAKICBzdW1tYXJpc2UobmxzX2NvbmMgPSBtZWFuKG5sc19jb25jKSkKCnJjX3Bsb3RfYXZnIDwtIGZ1bmN0aW9uKHByb3RlaW4gPSAiTlVMTCIpIHsKICBzaW1fY29tYmluZWQgJT4lIAogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAic2FtcGxlIikgJT4lIAogIGdyb3VwX2J5KHhwb25lbnRfaWQsIHNpbV9udW1iZXIsIGFzc2F5LCBudW1fcmVwc191c2VkKSAlPiUKICBzdW1tYXJpc2UoLmZpdHRlZCA9IG1lYW4oLmZpdHRlZCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihhc3NheSA9PSBwcm90ZWluKSAlPiUgCiAgbXV0YXRlKG51bV9yZXBzX3VzZWQgPSBhcy5jaGFyYWN0ZXIobnVtX3JlcHNfdXNlZCkpICU+JSAKICBnZ3Bsb3QoLixhZXMoeHBvbmVudF9pZCwgbG9nKC5maXR0ZWQgKzEpLCAKICAgICAgICAgICAgICAgY29sb3IgPSBudW1fcmVwc191c2VkKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IHJjX2F2ZyAlPiUgZmlsdGVyKGFzc2F5ID09IHByb3RlaW4pLCBhZXMoeHBvbmVudF9pZCwgbG9nKG5sc19jb25jICsgMSkpLCAKICAgICAgICAgICAgIGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUwKCJSdW4gQ29udHJvbHMgRm9yICIsIHByb3RlaW4pLCAKICAgICAgIHN1YnRpdGxlID0gIkRhcmsgQmx1ZSBQb2ludHMgYXJlIGZpdHRlZCB2YWx1ZXMgdXNpbmcgYWxsIDI0IHN0YW5kYXJkcyIpCn0KCgptYXAobGlzdF9vZl9wcm90ZWlucywgfiByY19wbG90X2F2Zyhwcm90ZWluID0gLngpKQpgYGAKCgoKCgoKCgoKCgoKIyMjIERlbGV0ZSBhIHN0YW5kYXJkICAgCgojIyMjIFJlcGxpY2F0ZXMgNCAgICAKCgoKCiMjIyMgUmVwbGljYXRlcyAzICAgCgoKCgoKMS4gRm9yIGVhY2ggcHJvdGVpbiwgZml0IGEgbW9kZWwgdXNpbmcgYWxsIDI0IHN0YW5kYXJkcyBhbmQgZml4IGl0ICAKMi4gVGhlbiBmb3IgZWFjaCBwcm90ZWluLCBzYW1wbGUgYSBzZXQgb2YgUkNzIGFuZCBwcmVkaWN0IHRoZWlyIGNvbmNlbnRyYXRpb25zIGJhc2VkIG9uIHRoZSBtb2RlbC4gICAKMy4gCgoKCgoKIyMjIEZpeCBzdGFuZGFyZCwgY2hhbmdlIG51bWJlciBvZiByZXBsaWNhdGVzIGluIHRoZSBSQ3MgICAKCmBgYHtyfQptb2RlbHMgPC0gbWFwKGxpc3Rfb2ZfcHJvdGVpbnMsICB+IGZpdF81cGwoZGYgPSBjb21iaW5lZF9zdGFuZGFyZHMgJT4lIGZpbHRlcihhc3NheSA9PSAueCkpKQpuYW1lcyhtb2RlbHMpIDwtIGxpc3Rfb2ZfcHJvdGVpbnMKbW9kZWxzICU+JQogIHB1cnJyOjpwbHVjaygiQUZQIikKCmBgYAoKCmBgYHtyfQppdGVyYXRlX21vZGVsX3JjIDwtIGZ1bmN0aW9uKHJlcGxpY2F0ZXMgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlaW4gPSAiTlVMTCIpIHsKICAKICBzYW1wbGVkX2RmIDwtIGNvbWJuKDI0LCByZXBsaWNhdGVzKSAlPiUKICAgIGFzLm1hdHJpeCgpICU+JQogICAgZGF0YS5mcmFtZSgpICU+JQogICAgc2VsZWN0KHNhbXBsZSgxOm5jb2woLiksIDEpKSAlPiUKICAgIHJlbmFtZSh3ZWxsX2NvbHVtbiA9IDEpICU+JQogICAgaW5uZXJfam9pbiguLCBuZXdfY29tYmluZWQpICU+JSAKICAgIGZpbHRlcihhc3NheSA9PSBhcy5jaGFyYWN0ZXIocHJvdGVpbikpICU+JSAKICAgIGdyb3VwX2J5KHhwb25lbnRfaWQpICU+JSAKICAgIG11dGF0ZShjdiA9IDEwMCpzZChtZWRpYW5fbWZpKS9tZWFuKG1lZGlhbl9tZmkpKSAlPiUgCiAgICB1bmdyb3VwKCkKICAKICB3ZWxsX2NvbHVtbnMgPC0gc2FtcGxlZF9kZiAlPiUgCiAgICBzZWxlY3Qod2VsbF9jb2x1bW4pICU+JSAKICAgIGRpc3RpbmN0KHdlbGxfY29sdW1uKQogIAogICAjZml0X21vZCA8LSBmaXRfNXBsKGRmID0gc3RhbmRhcmRfZGYpICAgCiAgICNzdGFuZGFyZF9kZiA8LSBicm9vbTo6YXVnbWVudChmaXRfbW9kLCBzdGFuZGFyZF9kZikgJT4lIAogICAgI3JlbmFtZShubHNfY29uYyA9IC5maXR0ZWQpICAKICAKICAgCiAgIHJjIDwtIHJjX2NhbGN1bGF0ZWQgJT4lIAogICAgZmlsdGVyKGFzc2F5ID09IGFzLmNoYXJhY3Rlcihwcm90ZWluKSkgJT4lCiAgICBpbm5lcl9qb2luKHdlbGxfY29sdW1ucykKICAKICAjc2FtcGxlZF9kZiA8LSBiaW5kX3Jvd3Moc2FtcGxlZF9kZiwgcmMpCgogICMjIHRoaXMgd2lsbCBoYXZlIGJhY2tjYWxjdWxhdGVkIENzIAogIGZpdF9tb2QgPC0gbW9kZWxzICU+JSBwbHVjayhwcm90ZWluKSAKICBhdWdtZW50ZWRfZGYgPC0gYnJvb206OmF1Z21lbnQoZml0X21vZCwgbmV3ZGF0YSA9IHJjKSAlPiUgCiAgICBtdXRhdGUobnVtX3JlcHNfdXNlZCA9IHJlcChyZXBsaWNhdGVzLCBucm93KC4pKSkKICAKICByZXR1cm4oYXVnbWVudGVkX2RmKQp9CgpgYGAKCgoKCgpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KcmNfcmVwc18yIDwtIGltYXBfZGZyKDE6MTAwLCB+bWFwX2RmcihsaXN0X29mX3Byb3RlaW5zLCB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0ZV9tb2RlbF9yYyhyZXBsaWNhdGVzID0gMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlaW4gPSAueCkpLCAKICAgICAgICAgICAgICAgIC5pZCA9ICJzaW1fbnVtYmVyIikKCnJjX3JlcHNfMyA8LSBpbWFwX2RmcigxOjEwMCwgfm1hcF9kZnIobGlzdF9vZl9wcm90ZWlucywgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGVfbW9kZWxfcmMocmVwbGljYXRlcyA9IDMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWluID0gLngpKSwgCiAgICAgICAgICAgICAgICAuaWQgPSAic2ltX251bWJlciIpCgpyY19yZXBzXzQgPC0gaW1hcF9kZnIoMToxMDAsIH5tYXBfZGZyKGxpc3Rfb2ZfcHJvdGVpbnMsIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRlX21vZGVsX3JjKHJlcGxpY2F0ZXMgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVpbiA9IC54KSksIAogICAgICAgICAgICAgICAgLmlkID0gInNpbV9udW1iZXIiKQoKcmNfcmVwc181IDwtIGltYXBfZGZyKDE6MTAwLCB+bWFwX2RmcihsaXN0X29mX3Byb3RlaW5zLCB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0ZV9tb2RlbF9yYyhyZXBsaWNhdGVzID0gNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlaW4gPSAueCkpLCAKICAgICAgICAgICAgICAgIC5pZCA9ICJzaW1fbnVtYmVyIikKYGBgCgoKYGBge3J9CnJjX3NpbV9jb21iaW5lZCA8LSBiaW5kX3Jvd3MocmNfcmVwc18yLCByY19yZXBzXzMsIHJjX3JlcHNfNCwgcmNfcmVwc181KSAgCmBgYAoKCmBgYHtyfQpyY19zaW1fY29tYmluZWQKYGBgCgoKYGBge3J9CnJjX2F2ZyA8LSByY19jYWxjdWxhdGVkICU+JSAKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInNhbXBsZSIpICU+JSAKICBncm91cF9ieShhc3NheSwgeHBvbmVudF9pZCkgJT4lIAogIHN1bW1hcmlzZShubHNfY29uYyA9IG1lYW4obmxzX2NvbmMpKQoKcmNfcGxvdF9hdmcgPC0gZnVuY3Rpb24ocHJvdGVpbiA9ICJOVUxMIikgewogIHJjX3NpbV9jb21iaW5lZCAlPiUgCiAgZmlsdGVyKHNhbXBsZV90eXBlID09ICJzYW1wbGUiKSAlPiUgCiAgZ3JvdXBfYnkoeHBvbmVudF9pZCwgc2ltX251bWJlciwgYXNzYXksIG51bV9yZXBzX3VzZWQpICU+JQogIHN1bW1hcmlzZSguZml0dGVkID0gbWVhbiguZml0dGVkKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKGFzc2F5ID09IHByb3RlaW4pICU+JSAKICBtdXRhdGUobnVtX3JlcHNfdXNlZCA9IGFzLmNoYXJhY3RlcihudW1fcmVwc191c2VkKSkgJT4lIAogIGdncGxvdCguLGFlcyh4cG9uZW50X2lkLCBsb2coLmZpdHRlZCArMSksIAogICAgICAgICAgICAgICBjb2xvciA9IG51bV9yZXBzX3VzZWQpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDEuNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gcmNfYXZnICU+JSBmaWx0ZXIoYXNzYXkgPT0gcHJvdGVpbiksIGFlcyh4cG9uZW50X2lkLCBsb2cobmxzX2NvbmMgKyAxKSksIAogICAgICAgICAgICAgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxKSArIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZTAoIlJ1biBDb250cm9scyBGb3IgIiwgcHJvdGVpbiksIAogICAgICAgc3VidGl0bGUgPSAiRGFyayBCbHVlIFBvaW50cyBhcmUgZml0dGVkIHZhbHVlcyB1c2luZyBhbGwgMjQgc3RhbmRhcmRzIikKfQoKCm1hcChsaXN0X29mX3Byb3RlaW5zLCB+IHJjX3Bsb3RfYXZnKHByb3RlaW4gPSAueCkpCmBgYAoKCmBgYHtyfQpyY19jdl9wbG90IDwtIGZ1bmN0aW9uKHByb3RlaW4gPSAiTlVMTCIpIHsKICByY19zaW1fY29tYmluZWQgJT4lIAogIGdyb3VwX2J5KGFzc2F5LCBudW1fcmVwc191c2VkLCB4cG9uZW50X2lkKSAlPiUgCiAgc3VtbWFyaXNlKGF2ZyA9IG1lYW4obG9nKC5maXR0ZWQgKyAxKSwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIHN0ZF9kZXYgPSBzZChsb2coLmZpdHRlZCArIDEpLCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgY3YgPSAxMDAqKHN0ZF9kZXYpL2F2ZykgJT4lIAogIG11dGF0ZSh4cG9uZW50X2lkID0gZmN0X3Jlb3JkZXIoeHBvbmVudF9pZCwgY3YpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoYXNzYXkgPT0gcHJvdGVpbikgJT4lIAogIG11dGF0ZShudW1fcmVwc191c2VkID0gYXMuY2hhcmFjdGVyKG51bV9yZXBzX3VzZWQpKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHhwb25lbnRfaWQsIGN2KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IG51bV9yZXBzX3VzZWQpKSArIAogICAgbGFicyh0aXRsZSA9IHBhc3RlMChwcm90ZWluKSkgKyAKICAgIHRoZW1lX2NsYXNzaWMoKSAKfQptYXAobGlzdF9vZl9wcm90ZWlucywgfiByY19jdl9wbG90KHByb3RlaW4gPSAueCkpIAoKCgoKICByY19zaW1fY29tYmluZWQgJT4lIAogIGdyb3VwX2J5KGFzc2F5LCBudW1fcmVwc191c2VkLCB4cG9uZW50X2lkKSAlPiUgCiAgc3VtbWFyaXNlKGF2ZyA9IG1lYW4obG9nKC5maXR0ZWQgKyAxKSwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIHN0ZF9kZXYgPSBzZChsb2coLmZpdHRlZCArIDEpLCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgY3YgPSAxMDAqKHN0ZF9kZXYpL2F2ZykgJT4lIAogIG11dGF0ZShhc3NheSA9IGZjdF9yZW9yZGVyKGFzc2F5LCBjdikpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShudW1fcmVwc191c2VkID0gYXMuY2hhcmFjdGVyKG51bV9yZXBzX3VzZWQpKSAlPiUgCiAgZ2dwbG90KC4sYWVzKGFzc2F5LCBjdikpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBudW1fcmVwc191c2VkKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpKSArIAogIGxhYnModGl0bGUgPSAiIikgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBmYWNldF93cmFwKHZhcnMoeHBvbmVudF9pZCkpCiAgCiAgCmBgYAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK